/* Inspector.m - Copyright 1993  Steve Ludtke */
/* Nothing too exciting here. This just acts as a connection between */
/* the inspector panel and the rest of the program. Most of the */
/* actual work is done elsewhere */
/* No comments here, see Inspector.h for brief descriptions */

#import "Mtypes.h"
#import "Inspector.h"
#import "MolObj.h"
#import "SelectView.h"
#import "AminoView.h"

extern ACID acid[AADEF];

@implementation Inspector

- startup:(Molecule *)Mol :(int)Nmol :(struct ELINFO *)Elinfo
{
mol=Mol;
nmol=Nmol;
elinfo=Elinfo;
aminoIns=[aminoIns contentView];
atabIns=[atabIns contentView];
atomIns=[atomIns contentView];
mode= -1;
nlist=nsel=0;
size=1.3;
list=NULL;
return self;
}

-update:(int)Nmol :(int)level
{
nmol=Nmol;
if (nmol==0) {
	[[abcount cellAt:0 :0] setStringValue:""];
	[[abcount cellAt:1 :0] setStringValue:""];
}
else {
	[[abcount cellAt:0 :0] setIntValue:mol[0].numa];
	[[abcount cellAt:1 :0] setIntValue:mol[0].numlb];
}

if (mode==0||mode==-1) [self a_insp:self];
else if (mode==1&&level>=U_BONDS) [self m_insp:self];
else if (mode==1) [self m_upd:self];
/*else if (mode==2) [self t_insp:self];*/
return self;
}

-newMol
{
mode= -1;
return self;
}

- a_bondAng:sender
{
float d;
char s[80];
int i,n[3];

if (nsel!=3) { [a_message setStringValue:"Select 3 atoms first"]; return self;}

for (i=0; i<3; i++) n[i]=list[i].stab;

d=[molobj bondAng:n[0] :n[1] :n[2]]*180.0/M_PI;

for (i=0; i<2; i++) {
	if (mol[0].atom[n[i]].bnd[0]!=n[i+1]&&mol[0].atom[n[i]].bnd[1]!=n[i+1]&& mol[0].atom[n[i]].bnd[2]!=n[i+1]&&mol[0].atom[n[i]].bnd[3]!=n[i+1]) break;
}
if (i==2) sprintf(s,"Angle=%-5.2f deg",d);
else sprintf(s,"Nonbonded, angle=%5.2f",d);

[a_message setStringValue:s];
return self;
}

- a_bondLen:sender
{
int n,n1;
float d;
char s[80];

if (nsel!=2) { [a_message setStringValue:"Select 2 atoms first"]; return self;}
n=list[0].stab;
n1=list[1].stab;

d=sqrt(SQR(mol[0].coord[n][0]-mol[0].coord[n1][0])+SQR(mol[0].coord[n][1]-mol[0].coord[n1][1])+SQR(mol[0].coord[n][2]-mol[0].coord[n1][2]));

if (mol[0].atom[n].bnd[0]!=n1&&mol[0].atom[n].bnd[1]!=n1&& mol[0].atom[n].bnd[2]!=n1&&mol[0].atom[n].bnd[3]!=n1) {
	sprintf(s,"Nonbonded distance=%4.2f†",d);
}
else sprintf(s,"Distance=%4.2f†",d);

[a_message setStringValue:s];
return self;
}

- a_dihedral:sender
{
float d;
char s[80];
int i,n[4];

if (nsel!=4) { [a_message setStringValue:"Select 4 atoms first"]; return self;}

for (i=0; i<4; i++) n[i]=list[i].stab;

d=[molobj dihedral:n[0] :n[1] :n[2] :n[3]]*180.0/M_PI;

for (i=0; i<3; i++) {
	if (mol[0].atom[n[i]].bnd[0]!=n[i+1]&&mol[0].atom[n[i]].bnd[1]!=n[i+1]&& mol[0].atom[n[i]].bnd[2]!=n[i+1]&&mol[0].atom[n[i]].bnd[3]!=n[i+1]) break;
}
if (i==3) sprintf(s,"dihedral=%-5.2f deg",d);
else sprintf(s,"nonbonded, angle=%5.2f",d);

[a_message setStringValue:s];
return self;
}

- a_insp:sender
{
int i,j;
[self newInsp];
mode=0;
[inspectBox setContentView:atomIns];
if (nlist!=mol[0].numa) {
	if (list!=NULL) free(list);
	list=malloc(sizeof(struct SELDAT)*mol[0].numa);
	nlist=mol[0].numa;
}

for (i=0; i<nlist; i++) {
	j=mol[0].atom[i].anum;
	sprintf(list[i].text,"%3d  %c%c",i, elinfo[j].name[0],elinfo[j].name[1]);
}
nsel=0;

[a_select setData:nlist :list :self];
[a_select setHeader:" N  ATOM"];
[inspectBox display];
return self;
}

- t_insp:sender
{
int i;

[self newInsp];
mode=2;
[inspectBox setContentView:atabIns];
if (list!=NULL) free(list);
list=malloc(sizeof(struct SELDAT)*NEL);
nlist=NEL;

for (i=0; i<nlist; i++) {
	sprintf(list[i].text,"%-3d  %c%c",i+1, elinfo[i].name[0],elinfo[i].name[1]);
}

[t_select setData:nlist :list :self];
[t_select setHeader:"N   SYMB"];
[inspectBox display];
return self;
}

- newInsp
{
switch (mode) 
{
case 0:
	[a_select deselectAll];
	[self deselected:0 :0];
	break;
case 1:
	break;
case 2:
	[t_select deselectAll];
	[self deselected:0 :0];
	break;
}
return self;
}

- t_newSize:sender
{
int i;

size=[sender floatValue];
for (i=0; i<NEL; i++) elinfo[i].rad=size*elinfo[i].arad;
[molobj update:U_POS];
return self;
}

- t_newColor:sender
{
int i;
float c;

for (i=0; i<3; i++) {
	c=[[t_color cellAt:i :0] floatValue];
	if (c<0.0) [[t_color cellAt:i :0] setFloatValue:0.0];
	if (c>1.0) [[t_color cellAt:i :0] setFloatValue:1.0];
}

if (nsel!=1) return self;
for (i=0; i<3; i++) 
	elinfo[list[0].stab].color[i]=[[t_color cellAt:i :0] floatValue];
return self;
}

- t_newRad:sender
{
float f;
if (nsel!=1) return self;
f=[[t_radii cellAt:0 :0] floatValue];
if (f<.01) [[t_radii cellAt:0 :0] setFloatValue:.01];
if (f>4.0) [[t_radii cellAt:0 :0] setFloatValue:4.0];
elinfo[list[0].stab].arad=[[t_radii cellAt:0 :0] floatValue];
elinfo[list[0].stab].rad=elinfo[list[0].stab].arad*size;
return self;
}

- t_revert:sender
{
char *bpath;
char s[80],t[100];
int i;
FILE *in;

bpath=(char *)[[NXBundle mainBundle] directory];
sprintf(t,"%s/Library/MolViewer.dat",getenv("HOME"));
in=fopen(t,"r");
if (in==NULL) {
	sprintf(t,"%s/MolViewer.dat",bpath);
	in=fopen(t,"r");
	if (in==NULL) { printf("No .rad\n"); exit(0); }
}
for (i=0; fgets(s,79,in)!=NULL&&i<NEL; i++) {
	elinfo[i].color[0]=elinfo[i].color[1]=elinfo[i].color[2]=.7;
	elinfo[i].name[0]=s[0];
	if (s[1]!='\t') elinfo[i].name[1]=s[1];
	else elinfo[i].name[1]=' ';
	sscanf(&s[2],"%f %f %f %f",&elinfo[i].arad,&elinfo[i].color[0],&elinfo[i].
		color[1],&elinfo[i].color[2]);
	elinfo[i].rad=size*elinfo[i].arad;
}
fclose(in);

if (t[0]=='\n') t[0]=' ';
sprintf(s,"Reverted to %s",t);
[t_message setStringValue:s];
[molobj update:U_POS];
return self;
}

- t_save:sender
{
char s[80];
FILE *out;
int i;

sprintf(s,"%s/Library/MolViewer.dat",getenv("HOME"));
out=fopen(s,"w");
if (out==NULL) {
	[t_message setStringValue:"Can't write to $HOME/Library"];
	return self;
}
for (i=0; i<NEL; i++) fprintf(out,"%c%c\t%5.3f\t%4.2f\t%4.2f\t%4.2f\n", 
	elinfo[i].name[0],elinfo[i].name[1],elinfo[i].arad,elinfo[i].color[0], 
	elinfo[i].color[1],elinfo[i].color[2]);
fclose(out);
strcat(s," written.");
[t_message setStringValue:s];
return self;
}

-t_update:sender
{
[molobj update:U_POS];
return self;
}

- m_insp:sender
{
int i;
[self newInsp];
mode=1;
[inspectBox setContentView:aminoIns];
[molobj findAA:self];
if (nlist!=mol[0].numaa) {
	if (list!=NULL) free(list);
	list=malloc(sizeof(struct SELDAT)*mol[0].numaa);
	nlist=mol[0].numaa;
}

for (i=0; i<nlist; i++) {
	sprintf(list[i].text,"%3d  %s  %7.2f  %7.2f  %7.2f",i+1, acid[mol[0].am[i].anum].d2,mol[0].am[i].omega/DRC,mol[0].am[i].phi/DRC, mol[0].am[i].psi/DRC);
}
nsel=0;

[m_select setData:nlist :list :self];
[m_select setHeader:" N   AA    omega     phi      psi"];
/*[m_select setGHeader:"                  w         f        y"]; */ 

[inspectBox display];
return self;
}

- m_upd:sender
{
int i;

for (i=0; i<nlist; i++) {
	sprintf(list[i].text,"%3d  %s  %7.2f  %7.2f  %7.2f",i+1, acid[mol[0].am[i].anum].d2,mol[0].am[i].omega/DRC,mol[0].am[i].phi/DRC, mol[0].am[i].psi/DRC);
}
nsel=0;

[inspectBox display];
return self;
}

-m_setAngS:sender
{
int n;
float a;

n=[sender selectedRow];
a=[[sender selectedCell] floatValue];
switch(n) {
case 0:
	[[m_angT cellAt:0 :0] setFloatValue:a];
	[molobj setOmega:a];
	break;
case 1:
	[[m_angT cellAt:1 :0] setFloatValue:a];
	[molobj setPhi:a];
	break;
case 2:
	[[m_angT cellAt:2 :0] setFloatValue:a];
	[molobj setPsi:a];
	break;
}

return self;
}

-m_setAngT:sender
{
int n;
float a;

n=[sender selectedRow];
a=[[sender selectedCell] floatValue];
switch(n) {
case 0:
	[[m_angS cellAt:0 :0] setFloatValue:a];
	[molobj setOmega:a];
	break;
case 1:
	[[m_angS cellAt:1 :0] setFloatValue:a];
	[molobj setPhi:a];
	break;
case 2:
	[[m_angS cellAt:2 :0] setFloatValue:a];
	[molobj setPsi:a];
	break;
}

return self;
}

-m_xfer:sender
{
char s[MAXSEQ+1];
int i;

for (i=0; i<nlist; i++) {
	s[i]=acid[mol[0].am[i].anum].d1[0];
}
s[i]=0;
[m_amview setSeqStr:self :s];
return self;
}

- selected:(int)n :(int)Nsel
{
int i,j;

nsel=Nsel;

switch (mode) {
case 0:
	[molobj setSelAtom:list];
	if (nsel>1) {
		for (i=0; i<4; i++) [[a_bond cellAt:i :0] setStringValue:""];
		for (i=0; i<3; i++) [[a_pos1 cellAt:i :0] setStringValue:""];
		for (i=0; i<2; i++) [[a_pos2 cellAt:i :0] setStringValue:""];
	} else {
		for (i=0; i<4; i++) {
			if ((j=mol[0].atom[n].bnd[i])==-1) 
				[[a_bond cellAt:i :0] setStringValue:""];
			else [[a_bond cellAt:i :0] setIntValue:j];
		}
		for (i=0; i<3; i++) [[a_pos1 cellAt:i :0] setFloatValue: 
			mol[0].coord[n][i]];
	}
	break;
case 1:
	for (i=0; i<nlist; i++) mol[0].am[i].sel=list[i].sel;
	if (nsel==1) {
		[[m_angS cellAt:0 :0] setFloatValue:mol[0].am[list[0].stab].omega/DRC];
		[[m_angS cellAt:1 :0] setFloatValue:mol[0].am[list[0].stab].phi/DRC];
		[[m_angS cellAt:2 :0] setFloatValue:mol[0].am[list[0].stab].psi/DRC];
		[[m_angT cellAt:0 :0] setFloatValue:mol[0].am[list[0].stab].omega/DRC];
		[[m_angT cellAt:1 :0] setFloatValue:mol[0].am[list[0].stab].phi/DRC];
		[[m_angT cellAt:2 :0] setFloatValue:mol[0].am[list[0].stab].psi/DRC];
	}
	break;
case 2:	
	if (nsel>1) {
		for (i=0; i<3; i++) [[t_color cellAt:i :0] setStringValue:""];
		for (i=0; i<2; i++) [[t_radii cellAt:i :0] setStringValue:""];
	}
	else {
		for (i=0; i<3; i++) [[t_color cellAt:i :0] setFloatValue:elinfo[n].color[i]];
		[[t_radii cellAt:0 :0] setFloatValue:elinfo[n].arad];
/*		[[t_radii cellAt:1 :0] setFloatValue:];*/
	}
	break;		
}
return self;
} 


- deselected:(int)n :(int)Nsel
{
int i;
nsel=Nsel;
switch (mode) {
case 0:
	for (i=0; i<4; i++) [[a_bond cellAt:i :0] setStringValue:""];
	for (i=0; i<3; i++) [[a_pos1 cellAt:i :0] setStringValue:""];
	for (i=0; i<2; i++) [[a_pos2 cellAt:i :0] setStringValue:""];
	[molobj setSelAtom:list];
	break;
case 1:
	for (i=0; i<nlist; i++) mol[0].am[i].sel=list[i].sel;
	break;	
case 2:
	for (i=0; i<3; i++) [[t_color cellAt:i :0] setStringValue:""];
	for (i=0; i<2; i++) [[t_radii cellAt:i :0] setStringValue:""];
	break;
}
return self;
}
@end
